home *** CD-ROM | disk | FTP | other *** search
/ Symantec Visual Cafe for Java 2.5 / symantec-visual-cafe-2.5-database-dev-edition.iso / Visual Cafe Pro v1.0 / TUTORIAL.BIN / Bignum.class (.txt) < prev    next >
Encoding:
Java Class File  |  1997-01-30  |  24.6 KB  |  1,679 lines

  1. package symjava.lang;
  2.  
  3. import java.util.Random;
  4.  
  5. public final class Bignum extends Number {
  6.    private static int[] smallPrimes = new int[51];
  7.    public static final int ROUND_STATISTICAL = -1;
  8.    public static final int NO_ROUNDING = 9;
  9.    public static final int ROUND_ABOVE_5 = 5;
  10.    public static final int ROUND_ABOVE_4 = 4;
  11.    public static final int ROUND_ALWAYS = 0;
  12.    private static final int MAXSCALE = 1073741823;
  13.    private int[] value;
  14.    private int scale;
  15.    private boolean negative;
  16.    private static int roundingValue;
  17.    static final int SRADIX = 30;
  18.    private static final int BASE = 1073741824;
  19.    private static final long MASK = 1073741823L;
  20.    public static final Bignum ZERO;
  21.    public static final Bignum ONE;
  22.    public static final Bignum TWO;
  23.  
  24.    public static void setRoundingOption(int val) {
  25.       switch (val) {
  26.          case -1:
  27.             roundingValue = -1;
  28.             return;
  29.          case 0:
  30.             roundingValue = 0;
  31.             return;
  32.          case 4:
  33.             roundingValue = 4;
  34.             return;
  35.          case 5:
  36.             roundingValue = 5;
  37.             return;
  38.          case 9:
  39.             roundingValue = 9;
  40.             return;
  41.          default:
  42.             if (val < 0 || val > 9) {
  43.                throw new IllegalArgumentException("Attempt to set invalid RoundingOption");
  44.             }
  45.       }
  46.    }
  47.  
  48.    public static int getRoundingOption() {
  49.       return roundingValue;
  50.    }
  51.  
  52.    public Bignum(String s) {
  53.       this.init(s, -1);
  54.    }
  55.  
  56.    public Bignum(String s, int scale) {
  57.       verifyScale(scale);
  58.       this.init(s, scale);
  59.    }
  60.  
  61.    public Bignum(int x, int scale) {
  62.       verifyScale(scale);
  63.       if (x < 0) {
  64.          this.negative = true;
  65.          x *= -1;
  66.          if (x < 0) {
  67.             int[] v = new int[]{0, 2};
  68.             this.value = v;
  69.             this._setScale(scale);
  70.             return;
  71.          }
  72.       } else {
  73.          this.negative = false;
  74.       }
  75.  
  76.       int digit0 = (int)((long)x & 1073741823L);
  77.       long carry = (long)x >> 30;
  78.       int digit1 = (int)(carry & 1073741823L);
  79.       if (digit1 > 0) {
  80.          int[] v = new int[]{digit0, digit1};
  81.          this.value = v;
  82.       } else {
  83.          int[] v = new int[]{digit0};
  84.          this.value = v;
  85.       }
  86.  
  87.       this._setScale(scale);
  88.    }
  89.  
  90.    public Bignum(int x) {
  91.       this(x, 0);
  92.    }
  93.  
  94.    public Bignum(long x, int scale) {
  95.       verifyScale(scale);
  96.       if (x < 0L) {
  97.          this.negative = true;
  98.          x *= -1L;
  99.          if (x < 0L) {
  100.             int[] v = new int[]{0, 0, 8};
  101.             this.value = v;
  102.             this._setScale(scale);
  103.             return;
  104.          }
  105.       } else {
  106.          this.negative = false;
  107.       }
  108.  
  109.       int digit0 = (int)(x & 1073741823L);
  110.       long carry = x >> 30;
  111.       int digit1 = (int)(carry & 1073741823L);
  112.       carry >>= 30;
  113.       int digit2 = (int)(carry & 1073741823L);
  114.       if (digit2 > 0) {
  115.          int[] v = new int[]{digit0, digit1, digit2};
  116.          this.value = v;
  117.       } else if (digit1 > 0) {
  118.          int[] v = new int[]{digit0, digit1};
  119.          this.value = v;
  120.       } else {
  121.          int[] v = new int[]{digit0};
  122.          this.value = v;
  123.       }
  124.  
  125.       this._setScale(scale);
  126.    }
  127.  
  128.    public Bignum(long x) {
  129.       this(x, 0);
  130.    }
  131.  
  132.    public Bignum(double x, int scale) {
  133.       verifyScale(scale);
  134.       Double d = new Double(x);
  135.       this.init(d.toString(), scale);
  136.    }
  137.  
  138.    public Bignum(Bignum x) {
  139.       this.scale = x.scale;
  140.       this.value = new int[x.value.length];
  141.       System.arraycopy(x.value, 0, this.value, 0, this.value.length);
  142.       this.negative = x.negative;
  143.    }
  144.  
  145.    public Bignum(Bignum x, int scale) {
  146.       verifyScale(scale);
  147.       this.scale = x.scale;
  148.       this.value = new int[x.value.length];
  149.       System.arraycopy(x.value, 0, this.value, 0, this.value.length);
  150.       this.negative = x.negative;
  151.       if (this.scale != scale) {
  152.          this._setScale(scale);
  153.       }
  154.  
  155.    }
  156.  
  157.    public static Bignum createFromByteArray(byte[] byteArray) {
  158.       Bignum r = new Bignum(0);
  159.       r.scale = 0;
  160.       r.negative = false;
  161.       r.value = new int[byteArray.length / 4 + 2];
  162.       long carry = 0L;
  163.  
  164.       for(int i = 0; i < byteArray.length; ++i) {
  165.          int c = byteArray[i] & 255;
  166.          carry = (long)c;
  167.  
  168.          for(int k = 0; k < r.value.length; ++k) {
  169.             long di = (long)r.value[k];
  170.             r.value[k] = (int)((di << 8 | carry) & 1073741823L);
  171.             carry = di >> 22;
  172.          }
  173.  
  174.          if (carry != 0L) {
  175.             r.value[r.value.length - 1] = (int)(carry & 1073741823L);
  176.          }
  177.       }
  178.  
  179.       return r;
  180.    }
  181.  
  182.    public byte[] toByteArray() {
  183.       int i = this.significantBits();
  184.       if (i <= 0) {
  185.          byte[] b = new byte[]{0};
  186.       }
  187.  
  188.       int j = i / 8;
  189.       if (i % 8 > 0) {
  190.          ++j;
  191.       }
  192.  
  193.       byte[] outArray = new byte[j];
  194.       int[] r = new int[this.value.length];
  195.       System.arraycopy(this.value, 0, r, 0, this.value.length);
  196.  
  197.       for(int var8 = outArray.length - 1; var8 >= 0; --var8) {
  198.          outArray[var8] = (byte)(r[0] & 255);
  199.          int carry = 0;
  200.  
  201.          for(int var7 = this.value.length - 1; var7 >= 0; --var7) {
  202.             int val = r[var7];
  203.             r[var7] = val >>> 8 | carry;
  204.             carry = (int)((long)(val << 22) & 1073741823L);
  205.          }
  206.       }
  207.  
  208.       return outArray;
  209.    }
  210.  
  211.    public static Bignum createFromIntegerArray(int[] intArray) {
  212.       int[] t1 = new int[intArray.length + 1];
  213.  
  214.       for(int i = 0; i < intArray.length; ++i) {
  215.          t1[i] = (int)((long)intArray[i] & 1073741823L);
  216.       }
  217.  
  218.       Bignum r = new Bignum(t1);
  219.       r.scale = 0;
  220.       r.negative = false;
  221.       return r;
  222.    }
  223.  
  224.    public static Bignum createFromScaled(long scaled, int s) {
  225.       verifyScale(s);
  226.       Bignum n = new Bignum(scaled);
  227.       if (s != 0) {
  228.          n.scale = s;
  229.       }
  230.  
  231.       return n;
  232.    }
  233.  
  234.    public static Bignum createFromRadixString(String s, int radix) {
  235.       Bignum r = new Bignum(0);
  236.       r.scale = 0;
  237.       r.negative = false;
  238.       r.value = new int[s.length() / (radix / 2) + 1];
  239.       boolean gotFirstDigit = false;
  240.  
  241.       for(int i = 0; i < s.length(); ++i) {
  242.          char c = s.charAt(i);
  243.          int a = Character.digit(c, radix);
  244.          if (a >= 0) {
  245.             gotFirstDigit = true;
  246.             int[] t1 = mulAndAdd(r.value, radix, a);
  247.             if (t1 != null) {
  248.                r.value = t1;
  249.             }
  250.          } else if (c == '-' && !gotFirstDigit) {
  251.             r.negative = true;
  252.          }
  253.       }
  254.  
  255.       return r;
  256.    }
  257.  
  258.    public static Bignum random(int bits, Random randomSeed) {
  259.       int ni = (bits - 1) / 30 + 1;
  260.       bits %= 30;
  261.       int[] rs = new int[ni];
  262.  
  263.       for(int i = 0; i < ni; ++i) {
  264.          int r = (int)((long)randomSeed.nextInt() & 1073741823L);
  265.          rs[i] = r;
  266.       }
  267.  
  268.       rs[ni - 1] &= (1 << bits) - 1;
  269.       Bignum rslt = new Bignum(rs);
  270.       rslt.dropLeadingZeroes();
  271.       return rslt;
  272.    }
  273.  
  274.    public int intValue() {
  275.       return (int)this.longValue();
  276.    }
  277.  
  278.    public long longValue() {
  279.       Bignum temp = new Bignum(this);
  280.       temp._setScale(0);
  281.       long lv = 0L;
  282.  
  283.       for(int i = temp.value.length < 3 ? temp.value.length - 1 : 2; i >= 0; --i) {
  284.          lv = (lv << 30) + (long)temp.value[i];
  285.       }
  286.  
  287.       return temp.negative ? -lv : lv;
  288.    }
  289.  
  290.    public float floatValue() {
  291.       return (float)this.doubleValue();
  292.    }
  293.  
  294.    public double doubleValue() {
  295.       Bignum temp = new Bignum(this);
  296.       temp._setScale(0);
  297.       double d = (double)0.0F;
  298.       int m = this.value.length - 1;
  299.       m = m > 4 ? m - 4 : 0;
  300.  
  301.       for(int i = this.value.length - 1; i >= m; --i) {
  302.          d = d * 1.073741823E9 + (double)this.value[i];
  303.       }
  304.  
  305.       if (m > 0) {
  306.          d *= Math.pow((double)30.0F, (double)m);
  307.       }
  308.  
  309.       this.subtract(temp);
  310.       if (this.scale != 0) {
  311.          double s = (double)1.0F;
  312.          s = Math.pow((double)10.0F, (double)this.scale);
  313.          d /= s;
  314.       }
  315.  
  316.       return this.negative ? -d : d;
  317.    }
  318.  
  319.    public String toString() {
  320.       if (this.value == null) {
  321.          return "null";
  322.       } else {
  323.          int l = this.value.length * 10 + 2;
  324.          if (l < this.scale) {
  325.             l = this.scale + 2;
  326.          }
  327.  
  328.          char[] x = new char[l];
  329.          int xi = x.length - 1;
  330.          int dp = xi - this.scale;
  331.          if (this.scale == 0) {
  332.             dp = -9999;
  333.          }
  334.  
  335.          int[] temp = new int[this.value.length];
  336.          System.arraycopy(this.value, 0, temp, 0, temp.length);
  337.          int i = temp.length - 1;
  338.  
  339.          while(i >= 0) {
  340.             if (temp[i] == 0) {
  341.                --i;
  342.             } else {
  343.                int rem = div0(temp, temp, 10);
  344.                x[xi--] = Character.forDigit(rem, 10);
  345.                if (xi == dp) {
  346.                   --xi;
  347.                }
  348.             }
  349.          }
  350.  
  351.          if (xi == x.length - 1) {
  352.             x[xi--] = '0';
  353.          }
  354.  
  355.          if (dp > 0) {
  356.             while(xi > dp) {
  357.                x[xi--] = '0';
  358.             }
  359.  
  360.             x[dp] = '.';
  361.          }
  362.  
  363.          String ms = this.negative ? "-" : "";
  364.          ms = ms + (new String(x, xi, x.length - xi)).trim();
  365.          return ms;
  366.       }
  367.    }
  368.  
  369.    public String toString(int radix) {
  370.       if (radix == 10) {
  371.          return this.toString();
  372.       } else if (this.value == null) {
  373.          return "null";
  374.       } else {
  375.          StringBuffer sb = new StringBuffer();
  376.          int[] temp = new int[this.value.length];
  377.          int len = 0;
  378.          System.arraycopy(this.value, 0, temp, 0, temp.length);
  379.          int i = temp.length - 1;
  380.  
  381.          while(i >= 0) {
  382.             if (temp[i] == 0) {
  383.                --i;
  384.             } else {
  385.                int rem = div0(temp, temp, radix);
  386.                sb.insert(0, Character.forDigit(rem, radix));
  387.                ++len;
  388.             }
  389.          }
  390.  
  391.          if (len == 0) {
  392.             sb.insert(0, '0');
  393.          }
  394.  
  395.          String ms = this.negative ? "-" : "";
  396.          ms = ms + sb.toString().trim();
  397.          return ms;
  398.       }
  399.    }
  400.  
  401.    public int getScale() {
  402.       return this.scale;
  403.    }
  404.  
  405.    public Bignum add(Bignum n) {
  406.       Bignum result = new Bignum(this);
  407.       Bignum x;
  408.       if (this.scale != n.scale) {
  409.          x = new Bignum(n);
  410.          x._setScale(this.scale);
  411.       } else {
  412.          x = n;
  413.       }
  414.  
  415.       if (result.negative == x.negative) {
  416.          result.value = add0(result.value, x.value);
  417.          return result;
  418.       } else if (!result.negative) {
  419.          int cmp = result.compareAbs(x);
  420.          if (cmp < 0) {
  421.             result = x.subtract(this);
  422.             result.negative = x.negative;
  423.             return result;
  424.          } else if (cmp > 0) {
  425.             result = result.subtract(x);
  426.             return result;
  427.          } else {
  428.             result.zero();
  429.             return result;
  430.          }
  431.       } else {
  432.          int cmp = result.compareAbs(x);
  433.          if (cmp < 0) {
  434.             result = x.subtract(this);
  435.             result.negative = x.negative;
  436.             return result;
  437.          } else if (cmp > 0) {
  438.             result = result.subtract(x);
  439.             return result;
  440.          } else {
  441.             result.zero();
  442.             return result;
  443.          }
  444.       }
  445.    }
  446.  
  447.    public Bignum subtract(Bignum n) {
  448.       Bignum result = new Bignum(this);
  449.       Bignum x;
  450.       if (this.scale != n.scale) {
  451.          x = new Bignum(n);
  452.          x._setScale(this.scale);
  453.       } else {
  454.          x = n;
  455.       }
  456.  
  457.       if (!result.negative && !x.negative) {
  458.          int c = result.compareAbs(x);
  459.          if (c == 0) {
  460.             result.zero();
  461.             return result;
  462.          } else if (c == 1) {
  463.             result.value = sub0(this.value, x.value);
  464.             return result;
  465.          } else {
  466.             result.value = sub0(x.value, this.value);
  467.             result.negative = true;
  468.             return result;
  469.          }
  470.       } else if (!result.negative && x.negative) {
  471.          result.value = add0(result.value, x.value);
  472.          return result;
  473.       } else if (result.negative && !x.negative) {
  474.          result.value = add0(result.value, x.value);
  475.          return result;
  476.       } else {
  477.          int c = result.compareAbs(x);
  478.          if (c == 0) {
  479.             result.zero();
  480.             return result;
  481.          } else if (c == -1) {
  482.             result.value = sub0(x.value, this.value);
  483.             result.negative = false;
  484.             return result;
  485.          } else {
  486.             result.value = sub0(this.value, x.value);
  487.             result.negative = true;
  488.             return result;
  489.          }
  490.       }
  491.    }
  492.  
  493.    public Bignum multiply(Bignum x) {
  494.       Bignum prod = new Bignum(this);
  495.       prod.scale += x.scale;
  496.       prod.negative = this.negative != x.negative;
  497.       Bignum m;
  498.       Bignum mx;
  499.       if (this.value.length > x.value.length) {
  500.          m = this;
  501.          mx = x;
  502.       } else {
  503.          m = x;
  504.          mx = this;
  505.       }
  506.  
  507.       if (mx.value.length == 1) {
  508.          prod.value = mul0(m.value, mx.value[0]);
  509.       } else {
  510.          prod.value = mul0(m.value, mx.value);
  511.       }
  512.  
  513.       if (prod.scale != this.scale) {
  514.          prod._setScale(this.scale);
  515.       }
  516.  
  517.       prod.dropLeadingZeroes();
  518.       return prod;
  519.    }
  520.  
  521.    public Bignum divide(Bignum x) {
  522.       if (x.compareAbs(ZERO) == 0) {
  523.          throw new ArithmeticException("Division by zero");
  524.       } else {
  525.          Bignum dividend = new Bignum(this);
  526.          Bignum divisor = new Bignum(x);
  527.          dividend.dropLeadingZeroes();
  528.          divisor.dropLeadingZeroes();
  529.          if (roundingValue < 9 || divisor.scale > dividend.scale) {
  530.             int scaleFactor = divisor.scale + 1;
  531.             ++dividend.scale;
  532.             int m1 = 9;
  533.             int m4 = 1000000000;
  534.  
  535.             int x1;
  536.             for(x1 = scaleFactor; x1 >= m1; x1 -= m1) {
  537.                dividend.value = mul0(dividend.value, m4);
  538.             }
  539.  
  540.             if (x1 > 0) {
  541.                dividend.value = mul0(dividend.value, pow(10, x1));
  542.             }
  543.          }
  544.  
  545.          Bignum quot = new Bignum(new int[dividend.value.length - divisor.value.length + 1]);
  546.          quot.negative = divisor.negative ? !dividend.negative : dividend.negative;
  547.          quot.scale = dividend.scale;
  548.          if (divisor.value.length == 1) {
  549.             div0(quot.value, dividend.value, divisor.value[0]);
  550.             quot._setScale(this.scale);
  551.             return quot;
  552.          } else {
  553.             int vLeftmostDigit = divisor.value[divisor.value.length - 1];
  554.             if (vLeftmostDigit >= 536870912) {
  555.                int[] tvalue = new int[dividend.value.length + 1];
  556.                System.arraycopy(dividend.value, 0, tvalue, 0, dividend.value.length);
  557.                tvalue[tvalue.length - 1] = 0;
  558.                dividend.value = tvalue;
  559.                div(dividend, divisor, quot);
  560.             } else {
  561.                int[] tvalue = new int[dividend.value.length + 1];
  562.                System.arraycopy(dividend.value, 0, tvalue, 0, dividend.value.length);
  563.                int d = 1073741824 / (vLeftmostDigit + 1);
  564.                dividend.value = mul0(tvalue, d);
  565.                divisor.value = mul0(divisor.value, d);
  566.                div(dividend, divisor, quot);
  567.             }
  568.  
  569.             quot._setScale(this.scale);
  570.             return quot;
  571.          }
  572.       }
  573.    }
  574.  
  575.    public Bignum[] integerDivide(Bignum x) {
  576.       if (x.compareAbs(ZERO) == 0) {
  577.          throw new ArithmeticException("Division by zero");
  578.       } else {
  579.          Bignum dividend = new Bignum(this);
  580.          Bignum divisor = new Bignum(x);
  581.          Bignum quot = _intDivide(divisor, dividend, this.scale);
  582.          Bignum[] r = new Bignum[]{quot, dividend};
  583.          return r;
  584.       }
  585.    }
  586.  
  587.    private static Bignum _intDivide(Bignum divisor, Bignum dividend, int scale) {
  588.       dividend.dropLeadingZeroes();
  589.       divisor.dropLeadingZeroes();
  590.       if (divisor.scale > dividend.scale) {
  591.          int scaleFactor = divisor.scale;
  592.          int m1 = 9;
  593.          int m4 = 1000000000;
  594.  
  595.          int x1;
  596.          for(x1 = scaleFactor; x1 >= m1; x1 -= m1) {
  597.             dividend.value = mul0(dividend.value, m4);
  598.          }
  599.  
  600.          if (x1 > 0) {
  601.             dividend.value = mul0(dividend.value, pow(10, x1));
  602.          }
  603.       }
  604.  
  605.       if (dividend.lessThan(divisor)) {
  606.          return new Bignum(0, 0);
  607.       } else {
  608.          Bignum quot = new Bignum(new int[dividend.value.length - divisor.value.length + 1]);
  609.          quot.negative = divisor.negative ? !dividend.negative : dividend.negative;
  610.          if (dividend.scale >= divisor.scale) {
  611.             quot.scale = dividend.scale - divisor.scale;
  612.          } else {
  613.             quot.scale = 0;
  614.          }
  615.  
  616.          if (divisor.value.length == 1) {
  617.             int rem = div0(quot.value, dividend.value, divisor.value[0]);
  618.             dividend.zero();
  619.             dividend.value[0] = (int)((long)rem & 1073741823L);
  620.             long carry = (long)rem >> 30;
  621.             int digit1 = (int)(carry & 1073741823L);
  622.             if (digit1 > 0) {
  623.                if (dividend.value.length < 2) {
  624.                   int[] newval = new int[]{dividend.value[0], digit1};
  625.                   dividend.value = newval;
  626.                } else {
  627.                   dividend.value[1] = digit1;
  628.                }
  629.             }
  630.  
  631.             return quot.scale > 0 ? truncate(quot) : quot;
  632.          } else {
  633.             int vLeftmostDigit = divisor.value[divisor.value.length - 1];
  634.             if (vLeftmostDigit >= 536870912) {
  635.                int[] tvalue = new int[dividend.value.length + 1];
  636.                System.arraycopy(dividend.value, 0, tvalue, 0, dividend.value.length);
  637.                tvalue[tvalue.length - 1] = 0;
  638.                dividend.value = tvalue;
  639.                div(dividend, divisor, quot);
  640.             } else {
  641.                int[] tvalue = new int[dividend.value.length + 1];
  642.                System.arraycopy(dividend.value, 0, tvalue, 0, dividend.value.length);
  643.                int d = 1073741824 / (vLeftmostDigit + 1);
  644.                dividend.value = mul0(tvalue, d);
  645.                divisor.value = mul0(divisor.value, d);
  646.                div(dividend, divisor, quot);
  647.                div0(dividend.value, dividend.value, d);
  648.             }
  649.  
  650.             if (quot.scale > 0) {
  651.                quot = truncate(quot);
  652.             }
  653.  
  654.             return quot;
  655.          }
  656.       }
  657.    }
  658.  
  659.    public Bignum remainder(Bignum x) {
  660.       if (x.compareAbs(ZERO) == 0) {
  661.          throw new ArithmeticException("Division by zero");
  662.       } else if (this.lessThan(x)) {
  663.          return new Bignum(this);
  664.       } else {
  665.          Bignum dividend = new Bignum(this);
  666.          Bignum divisor = new Bignum(x);
  667.          _intDivide(divisor, dividend, this.scale);
  668.          return dividend;
  669.       }
  670.    }
  671.  
  672.    public Bignum sqrt() {
  673.       Bignum g = new Bignum(this, this.scale + 1);
  674.       Bignum temp = new Bignum(0);
  675.       div0(g.value, g.value, 2);
  676.       Bignum eps = createFromScaled(5L, g.scale);
  677.  
  678.       for(Bignum diff = g.multiply(g).subtract(this); diff.compareAbs(eps) > 0; diff = temp.subtract(this)) {
  679.          temp.value = mul0(g.value, 2);
  680.          temp.scale = g.scale;
  681.          temp.negative = g.negative;
  682.          temp = diff.divide(temp);
  683.          g = g.subtract(temp);
  684.          temp = g.multiply(g);
  685.       }
  686.  
  687.       return g;
  688.    }
  689.  
  690.    public Bignum pow(int e) {
  691.       if (e == 0) {
  692.          return new Bignum((double)1.0F, this.scale);
  693.       } else {
  694.          Bignum ans = new Bignum(this);
  695.  
  696.          int[] t;
  697.          for(t = new int[]{1}; e > 1; e >>= 1) {
  698.             if ((e & 1) == 1) {
  699.                t = mul0(t, ans.value);
  700.             }
  701.  
  702.             ans.value = mul0(ans.value, ans.value);
  703.          }
  704.  
  705.          ans.value = mul0(ans.value, t);
  706.          ans.dropLeadingZeroes();
  707.          return ans;
  708.       }
  709.    }
  710.  
  711.    public boolean equals(Object obj) {
  712.       Bignum x = (Bignum)obj;
  713.       return this.compare(x) == 0;
  714.    }
  715.  
  716.    public boolean lessThan(Bignum x) {
  717.       return this.compare(x) == -1;
  718.    }
  719.  
  720.    public boolean lessThanOrEquals(Bignum x) {
  721.       return this.compare(x) != 1;
  722.    }
  723.  
  724.    public boolean greaterThan(Bignum x) {
  725.       return this.compare(x) == 1;
  726.    }
  727.  
  728.    public boolean greaterThanOrEquals(Bignum x) {
  729.       return this.compare(x) != -1;
  730.    }
  731.  
  732.    public int hashCode() {
  733.       int hash = 0;
  734.  
  735.       for(int i = 0; i < this.value.length; ++i) {
  736.          try {
  737.             hash += this.value[i];
  738.          } catch (Exception var3) {
  739.             hash = 0;
  740.          }
  741.       }
  742.  
  743.       return hash;
  744.    }
  745.  
  746.    public Bignum setScale(int scale) {
  747.       verifyScale(scale);
  748.       Bignum x = new Bignum(this, scale);
  749.       return x;
  750.    }
  751.  
  752.    public int significantBits() {
  753.       int i;
  754.       for(i = this.value.length - 1; i >= 0 && this.value[i] == 0; --i) {
  755.       }
  756.  
  757.       if (i < 0) {
  758.          return 0;
  759.       } else {
  760.          int val = this.value[i];
  761.  
  762.          for(i = 0; val != 0; ++i) {
  763.             val >>>= 1;
  764.          }
  765.  
  766.          int var5 = i * 30;
  767.          return var5 + i;
  768.       }
  769.    }
  770.  
  771.    public Bignum shiftRight(int shiftBits) {
  772.       if (shiftBits < 0) {
  773.          throw new IllegalArgumentException("Number of bits to shift may not be negative");
  774.       } else {
  775.          int nw = shiftBits / 30;
  776.          shiftBits %= 30;
  777.          int[] r = new int[this.value.length - nw];
  778.          System.arraycopy(this.value, nw, r, 0, this.value.length - nw);
  779.          int carry = 0;
  780.  
  781.          for(int i = r.length - 1; i >= 0; --i) {
  782.             int val = r[i];
  783.             r[i] = val >>> shiftBits | carry;
  784.             carry = (int)((long)(val << 30 - shiftBits) & 1073741823L);
  785.          }
  786.  
  787.          Bignum result = new Bignum(r);
  788.          result.dropLeadingZeroes();
  789.          return result;
  790.       }
  791.    }
  792.  
  793.    public Bignum shiftLeft(int shiftBits) {
  794.       if (shiftBits < 0) {
  795.          throw new IllegalArgumentException("Number of bits to shift may not be negative");
  796.       } else {
  797.          int nw = shiftBits / 30;
  798.          shiftBits %= 30;
  799.          int[] r = new int[this.value.length + nw + 1];
  800.          System.arraycopy(this.value, 0, r, nw, this.value.length);
  801.          int carry = 0;
  802.  
  803.          for(int i = 0; i < r.length - 1; ++i) {
  804.             int val = r[i];
  805.             r[i] = (int)((long)(val << shiftBits) | (long)carry & 1073741823L);
  806.             carry = val >>> 30 - shiftBits;
  807.          }
  808.  
  809.          if (carry != 0) {
  810.             r[r.length - 1] = carry;
  811.          }
  812.  
  813.          Bignum result = new Bignum(r);
  814.          result.dropLeadingZeroes();
  815.          return result;
  816.       }
  817.    }
  818.  
  819.    public Bignum modInverse(Bignum mod) {
  820.       Bignum i = new Bignum(mod);
  821.       Bignum h = new Bignum(this);
  822.       Bignum v = new Bignum(ZERO);
  823.  
  824.       Bignum x;
  825.       for(Bignum d = new Bignum(1); h.greaterThan(ZERO); v = x) {
  826.          Bignum[] tt = i.integerDivide(h);
  827.          Bignum t = tt[0];
  828.          x = h;
  829.          h = i.subtract(t.multiply(h));
  830.          i = x;
  831.          x = d;
  832.          d = v.subtract(t.multiply(d));
  833.       }
  834.  
  835.       if (!v.negative) {
  836.          return v.remainder(mod);
  837.       } else {
  838.          Bignum m = v.remainder(mod).multiply(mod);
  839.          return v.subtract(m);
  840.       }
  841.    }
  842.  
  843.    public Bignum modExp(Bignum exponent, Bignum mod) {
  844.       int ipr = exponent.significantBits() - 1;
  845.       int ibit = 1 << ipr % 30;
  846.       ipr /= 30;
  847.       int[] t = new int[this.value.length + 1];
  848.       Bignum rslt = new Bignum(ONE);
  849.  
  850.       while(ipr >= 0) {
  851.          rslt.value = mul0(rslt.value, rslt.value, t);
  852.          if (rslt.value != t) {
  853.             t = rslt.value;
  854.          }
  855.  
  856.          rslt = rslt.remainder(mod);
  857.          if ((exponent.value[ipr] & ibit) != 0) {
  858.             for(int i = 0; i < t.length; ++i) {
  859.                t[i] = 0;
  860.             }
  861.  
  862.             rslt.value = mul0(rslt.value, this.value, t);
  863.             if (rslt.value != t) {
  864.                t = rslt.value;
  865.             }
  866.  
  867.             rslt = rslt.remainder(mod);
  868.          }
  869.  
  870.          ibit >>>= 1;
  871.          if (ibit == 0) {
  872.             --ipr;
  873.             ibit = 536870912;
  874.          }
  875.  
  876.          for(int i = 0; i < t.length; ++i) {
  877.             t[i] = 0;
  878.          }
  879.       }
  880.  
  881.       return rslt;
  882.    }
  883.  
  884.    public boolean isProbablePrime() {
  885.       if ((this.value[0] & 1) != 1) {
  886.          return this.equals(TWO);
  887.       } else {
  888.          for(int i = 1; i < 11; ++i) {
  889.             int prime = smallPrimes[i];
  890.             if (this.quickMod(prime) == 0 && this.value[0] != prime) {
  891.                return false;
  892.             }
  893.          }
  894.  
  895.          return this.isProbablePrime0(50);
  896.       }
  897.    }
  898.  
  899.    private int quickMod(int d) {
  900.       int rem = 0;
  901.  
  902.       long temp;
  903.       for(int i = this.value.length; i-- > 0; rem = (int)(temp % (long)d)) {
  904.          temp = (long)(this.value[i] << 32 | rem);
  905.       }
  906.  
  907.       if (this.negative && rem != 0) {
  908.          rem = d - rem;
  909.       }
  910.  
  911.       return rem;
  912.    }
  913.  
  914.    private boolean isProbablePrime0(int n) {
  915.       Bignum wm1 = this.subtract(ONE);
  916.       int a = 0;
  917.       int l = 0;
  918.  
  919.       for(int i = 0; i < wm1.value.length && wm1.value[i] == 0; ++i) {
  920.          ++l;
  921.       }
  922.  
  923.       for(int val = wm1.value[l]; (val & 1) == 0; val >>>= 1) {
  924.          ++a;
  925.       }
  926.  
  927.       a = l * 30 + a;
  928.       if (a == 0) {
  929.          return false;
  930.       } else {
  931.          Bignum m = wm1.shiftRight(a);
  932.          Bignum z = new Bignum(3);
  933.          z = z.modExp(m, this);
  934.          if (!z.equals(ONE) && !z.equals(wm1)) {
  935.             for(int j = 1; j < a; ++j) {
  936.                z = z.multiply(z);
  937.                z = z.remainder(this);
  938.                if (z.equals(wm1)) {
  939.                   return true;
  940.                }
  941.  
  942.                if (z.equals(ONE)) {
  943.                   return false;
  944.                }
  945.             }
  946.  
  947.             int s = wm1.significantBits();
  948.  
  949.             for(int i = 0; i < n; ++i) {
  950.                Bignum b = random(s, new Random());
  951.                if (b.greaterThan(wm1)) {
  952.                   b = b.remainder(wm1);
  953.                }
  954.  
  955.                z = b.modExp(m, this);
  956.                if (!z.equals(ONE) && !z.equals(wm1)) {
  957.                   int var14;
  958.                   for(var14 = 1; var14 < a; ++var14) {
  959.                      z = z.modExp(TWO, this);
  960.                      if (z.equals(wm1)) {
  961.                         break;
  962.                      }
  963.  
  964.                      if (z.equals(ONE)) {
  965.                         return false;
  966.                      }
  967.                   }
  968.  
  969.                   if (var14 == a) {
  970.                      return false;
  971.                   }
  972.                }
  973.             }
  974.  
  975.             return true;
  976.          } else {
  977.             return true;
  978.          }
  979.       }
  980.    }
  981.  
  982.    private static void verifyScale(int scale) {
  983.       if (scale < 0) {
  984.          throw new IllegalArgumentException("Scale is negative");
  985.       } else if (scale > 1073741823) {
  986.          throw new IllegalArgumentException("Scale greater than maximum scale");
  987.       }
  988.    }
  989.  
  990.    public int compare(Bignum B) {
  991.       if (!this.negative && !B.negative) {
  992.          return this.compareAbs(B);
  993.       } else if (this.negative && !B.negative) {
  994.          return -1;
  995.       } else if (!this.negative && B.negative) {
  996.          return 1;
  997.       } else {
  998.          int r = this.compareAbs(B);
  999.          if (r != 0) {
  1000.             r *= -1;
  1001.          }
  1002.  
  1003.          return r;
  1004.       }
  1005.    }
  1006.  
  1007.    private int compareAbs(Bignum A) {
  1008.       Bignum B;
  1009.       if (A.scale == this.scale) {
  1010.          B = A;
  1011.       } else {
  1012.          B = new Bignum(A, this.scale);
  1013.       }
  1014.  
  1015.       int sigB;
  1016.       for(sigB = B.value.length - 1; sigB > 0 && B.value[sigB] == 0; --sigB) {
  1017.       }
  1018.  
  1019.       ++sigB;
  1020.  
  1021.       int sigA;
  1022.       for(sigA = this.value.length - 1; sigA > 0 && this.value[sigA] == 0; --sigA) {
  1023.       }
  1024.  
  1025.       ++sigA;
  1026.       if (sigA > sigB) {
  1027.          return 1;
  1028.       } else if (sigB > sigA) {
  1029.          return -1;
  1030.       } else if (sigA == 0 && sigB == 0) {
  1031.          return 0;
  1032.       } else {
  1033.          do {
  1034.             --sigA;
  1035.             if (sigA < 0) {
  1036.                return 0;
  1037.             }
  1038.  
  1039.             if (this.value[sigA] > B.value[sigA]) {
  1040.                return 1;
  1041.             }
  1042.          } while(this.value[sigA] >= B.value[sigA]);
  1043.  
  1044.          return -1;
  1045.       }
  1046.    }
  1047.  
  1048.    private void init(String s, int iscale) {
  1049.       boolean scaleGiven = true;
  1050.       this.scale = 0;
  1051.       int mantVal = 0;
  1052.       if (iscale < 0) {
  1053.          scaleGiven = false;
  1054.       }
  1055.  
  1056.       int inScale = 0;
  1057.       this.negative = false;
  1058.       if (scaleGiven) {
  1059.          this.value = new int[(s.length() + iscale) / 3 + 1];
  1060.       } else {
  1061.          this.value = new int[s.length() / 5 + 1];
  1062.       }
  1063.  
  1064.       int[] t1 = new int[]{10};
  1065.       boolean mant = false;
  1066.       boolean gotFirstDigit = false;
  1067.       boolean gotFirstExpDigit = false;
  1068.  
  1069.       for(int i = 0; i < s.length(); ++i) {
  1070.          char c = s.charAt(i);
  1071.          if (c >= '0' && c <= '9') {
  1072.             if (inScale != 0 && !mant) {
  1073.                ++inScale;
  1074.             }
  1075.  
  1076.             int a = Character.digit(c, 10);
  1077.             if (mant) {
  1078.                mantVal = mantVal * 10 + a;
  1079.                gotFirstExpDigit = true;
  1080.             } else {
  1081.                t1 = mulAndAdd(this.value, 10, a);
  1082.                if (t1 != null) {
  1083.                   this.value = t1;
  1084.                }
  1085.  
  1086.                gotFirstDigit = true;
  1087.             }
  1088.          } else if (c == '-') {
  1089.             if (mant) {
  1090.                if (!gotFirstExpDigit) {
  1091.                   mantVal = -mantVal;
  1092.                }
  1093.             } else if (!gotFirstDigit) {
  1094.                this.negative = true;
  1095.             }
  1096.          } else {
  1097.             if (c == '.' && inScale == 0) {
  1098.                inScale = 1;
  1099.             }
  1100.  
  1101.             if (c == 'E' || c == 'e') {
  1102.                mant = true;
  1103.             }
  1104.          }
  1105.       }
  1106.  
  1107.       if (mant) {
  1108.          if (inScale != 0) {
  1109.             this.scale = inScale - 1;
  1110.          } else {
  1111.             this.scale = 0;
  1112.          }
  1113.  
  1114.          if (mantVal < 0) {
  1115.             mantVal *= -1;
  1116.             this.divide((new Bignum(10, 0)).pow(mantVal));
  1117.          } else {
  1118.             this.value = mul0(this.value, (new Bignum(10, 0)).pow(mantVal).value);
  1119.          }
  1120.  
  1121.          if (scaleGiven) {
  1122.             this._setScale(iscale);
  1123.          }
  1124.  
  1125.       } else {
  1126.          if (inScale != 0) {
  1127.             --inScale;
  1128.             this.scale = inScale;
  1129.             if (scaleGiven && this.scale != iscale) {
  1130.                this._setScale(iscale);
  1131.                return;
  1132.             }
  1133.          } else {
  1134.             this.scale = 0;
  1135.             if (scaleGiven) {
  1136.                this._setScale(iscale);
  1137.             }
  1138.          }
  1139.  
  1140.       }
  1141.    }
  1142.  
  1143.    private void zero() {
  1144.       this.negative = false;
  1145.  
  1146.       for(int i = 0; i < this.value.length; ++i) {
  1147.          this.value[i] = 0;
  1148.       }
  1149.  
  1150.    }
  1151.  
  1152.    private void dropLeadingZeroes() {
  1153.       int i;
  1154.       for(i = this.value.length - 1; i >= 0 && this.value[i] == 0; --i) {
  1155.       }
  1156.  
  1157.       if (i < 0) {
  1158.          i = 0;
  1159.       }
  1160.  
  1161.       ++i;
  1162.       if (i < this.value.length) {
  1163.          int[] nval = new int[i];
  1164.          System.arraycopy(this.value, 0, nval, 0, i);
  1165.          this.value = nval;
  1166.       }
  1167.    }
  1168.  
  1169.    public static Bignum truncate(Bignum in) {
  1170.       if (in.scale == 0) {
  1171.          return new Bignum(in);
  1172.       } else {
  1173.          int scaleFactor = in.scale - 1;
  1174.          int[] tval = new int[1];
  1175.          tval[0] = 0;
  1176.          int m1 = 9;
  1177.          int m4 = 1000000000;
  1178.  
  1179.          int x;
  1180.          for(x = scaleFactor; x >= m1; x -= m1) {
  1181.             tval = mul0(tval, m4);
  1182.          }
  1183.  
  1184.          if (x > 0) {
  1185.             tval = mul0(tval, pow(10, x));
  1186.          }
  1187.  
  1188.          tval = add0(in.value, tval);
  1189.  
  1190.          for(x = scaleFactor + 1; x >= m1; x -= m1) {
  1191.             div0(tval, tval, m4);
  1192.          }
  1193.  
  1194.          if (x > 0) {
  1195.             div0(tval, tval, pow(10, x));
  1196.          }
  1197.  
  1198.          Bignum out = new Bignum(tval);
  1199.          out.scale = 0;
  1200.          out.negative = in.negative;
  1201.          return out;
  1202.       }
  1203.    }
  1204.  
  1205.    private void _setScale(int iscale) {
  1206.       verifyScale(iscale);
  1207.       if (iscale != this.scale) {
  1208.          if (iscale > this.scale) {
  1209.             for(int i = iscale - this.scale; i > 0; --i) {
  1210.                this.value = mul0(this.value, 10);
  1211.             }
  1212.  
  1213.             this.scale = iscale;
  1214.          } else {
  1215.             int tempRoundingValue = roundingValue;
  1216.             if (roundingValue == -1) {
  1217.                tempRoundingValue = 9;
  1218.             }
  1219.  
  1220.             int scaleFactor = this.scale - iscale - 1;
  1221.             int[] tval = new int[]{9 - tempRoundingValue};
  1222.             int m1 = 9;
  1223.             int m4 = 1000000000;
  1224.  
  1225.             int x;
  1226.             for(x = scaleFactor; x >= m1; x -= m1) {
  1227.                tval = mul0(tval, m4);
  1228.             }
  1229.  
  1230.             if (x > 0) {
  1231.                tval = mul0(tval, pow(10, x));
  1232.             }
  1233.  
  1234.             this.value = add0(this.value, tval);
  1235.  
  1236.             for(x = scaleFactor + 1; x >= m1; x -= m1) {
  1237.                div0(this.value, this.value, m4);
  1238.             }
  1239.  
  1240.             if (x > 0) {
  1241.                div0(this.value, this.value, pow(10, x));
  1242.             }
  1243.  
  1244.             if (roundingValue == -1 && (this.value[0] & 1) == 1) {
  1245.                int var10002 = this.value[0]++;
  1246.             }
  1247.  
  1248.             this.scale = iscale;
  1249.          }
  1250.       }
  1251.    }
  1252.  
  1253.    private static int[] mul0(int[] u, int[] v) {
  1254.       int n = u.length - 1;
  1255.       int m = v.length - 1;
  1256.       long k = 0L;
  1257.       int[] w = new int[u.length + v.length];
  1258.  
  1259.       for(int j = 0; j <= n; ++j) {
  1260.          k = 0L;
  1261.          int q = j;
  1262.  
  1263.          for(int i = 0; i <= m; ++i) {
  1264.             long uv = (long)u[j];
  1265.             long t = uv * (long)v[i] + (long)w[q] + k;
  1266.             w[q++] = (int)(t & 1073741823L);
  1267.             k = t >> 30;
  1268.          }
  1269.  
  1270.          while(k != 0L) {
  1271.             long uv = (long)w[q] + k;
  1272.             w[q++] = (int)(uv & 1073741823L);
  1273.             k = uv >> 30;
  1274.          }
  1275.       }
  1276.  
  1277.       if (w[w.length - 1] != 0) {
  1278.          return w;
  1279.       } else {
  1280.          int ul;
  1281.          for(ul = w.length - 1; ul > 0 && w[ul] == 0; --ul) {
  1282.          }
  1283.  
  1284.          ++ul;
  1285.          int[] w1 = new int[ul];
  1286.          System.arraycopy(w, 0, w1, 0, w1.length);
  1287.          return w1;
  1288.       }
  1289.    }
  1290.  
  1291.    private static int[] mul0(int[] u, int v) {
  1292.       int n = u.length - 1;
  1293.       long k = 0L;
  1294.       long x = (long)v & 1073741823L;
  1295.       int[] w = new int[u.length];
  1296.       if (x != 0L) {
  1297.          for(int i = 0; i <= n; ++i) {
  1298.             long uv = ((long)u[i] & 1073741823L) * x + k;
  1299.             w[i] = (int)(uv & 1073741823L);
  1300.             k = uv >> 30;
  1301.          }
  1302.  
  1303.          if (k != 0L) {
  1304.             int[] ww = new int[w.length + 1];
  1305.             System.arraycopy(w, 0, ww, 0, w.length);
  1306.             ww[ww.length - 1] = (int)k;
  1307.             w = ww;
  1308.          }
  1309.       }
  1310.  
  1311.       return w;
  1312.    }
  1313.  
  1314.    private static int[] add0(int[] u, int[] v) {
  1315.       int j = 0;
  1316.  
  1317.       int ul;
  1318.       for(ul = u.length - 1; ul > 0 && u[ul] == 0; --ul) {
  1319.       }
  1320.  
  1321.       int vl;
  1322.       for(vl = v.length - 1; vl > 0 && v[vl] == 0; --vl) {
  1323.       }
  1324.  
  1325.       ++ul;
  1326.       ++vl;
  1327.       if (ul < vl) {
  1328.          int[] temp = u;
  1329.          u = v;
  1330.          v = temp;
  1331.          int temp2 = ul;
  1332.          ul = vl;
  1333.          vl = temp2;
  1334.       }
  1335.  
  1336.       int[] w = new int[ul + 1];
  1337.       long carry = 0L;
  1338.  
  1339.       for(j = 0; j < vl; ++j) {
  1340.          long temp = (long)(u[j] + v[j]) + carry;
  1341.          carry = temp >> 30;
  1342.          w[j] = (int)(temp & 1073741823L);
  1343.       }
  1344.  
  1345.       while(carry != 0L && j < ul) {
  1346.          long temp = (long)u[j] + carry;
  1347.          w[j] = (int)(temp & 1073741823L);
  1348.          carry = temp >> 30;
  1349.          ++j;
  1350.       }
  1351.  
  1352.       if (carry == 0L && j < ul) {
  1353.          while(j < ul) {
  1354.             w[j] = u[j];
  1355.             ++j;
  1356.          }
  1357.       } else {
  1358.          w[j] = (int)(carry & 1073741823L);
  1359.       }
  1360.  
  1361.       return w;
  1362.    }
  1363.  
  1364.    private static int[] add0(int[] u, int v) {
  1365.       int j = 0;
  1366.  
  1367.       int ul;
  1368.       for(ul = u.length - 1; ul > 0 && u[ul] == 0; --ul) {
  1369.       }
  1370.  
  1371.       int[] w = new int[ul++ + 1];
  1372.       long carry = 0L;
  1373.       long temp = ((long)u[j] & 1073741823L) + ((long)v & 1073741823L);
  1374.       carry = temp >> 30;
  1375.       w[j] = (int)(temp & 1073741823L);
  1376.       ++j;
  1377.  
  1378.       while(carry != 0L && j < ul) {
  1379.          temp = (long)u[j] + carry;
  1380.          w[j] = (int)(temp & 1073741823L);
  1381.          carry = temp >> 30;
  1382.          ++j;
  1383.       }
  1384.  
  1385.       if (carry == 0L && j < ul) {
  1386.          while(j < ul) {
  1387.             w[j] = u[j];
  1388.             ++j;
  1389.          }
  1390.       }
  1391.  
  1392.       return w;
  1393.    }
  1394.  
  1395.    private static int[] sub0(int[] u, int[] v) {
  1396.       boolean borrow = false;
  1397.  
  1398.       int ul;
  1399.       for(ul = u.length - 1; ul > 0 && u[ul] == 0; --ul) {
  1400.       }
  1401.  
  1402.       int vl;
  1403.       for(vl = v.length - 1; vl > 0 && v[vl] == 0; --vl) {
  1404.       }
  1405.  
  1406.       int[] w = new int[ul + 1];
  1407.  
  1408.       int wj;
  1409.       int j;
  1410.       for(j = 0; j <= vl; borrow = wj < 0) {
  1411.          wj = u[j] - v[j] + (borrow ? -1 : 0);
  1412.          w[j++] = (int)((long)wj & 1073741823L);
  1413.       }
  1414.  
  1415.       if (borrow) {
  1416.          while(j <= ul) {
  1417.             w[j] = u[j] - (borrow ? 1 : 0);
  1418.             if (w[j++] >= 0) {
  1419.                break;
  1420.             }
  1421.          }
  1422.       }
  1423.  
  1424.       while(j <= ul) {
  1425.          w[j] = u[j];
  1426.          ++j;
  1427.       }
  1428.  
  1429.       return w;
  1430.    }
  1431.  
  1432.    private static int div0(int[] quotient, int[] dividend, int divisor) {
  1433.       long carry = 0L;
  1434.  
  1435.       for(int i = dividend.length - 1; i >= 0; --i) {
  1436.          long x = ((long)dividend[i] & 1073741823L) + (carry << 30);
  1437.          quotient[i] = (int)(x / ((long)divisor & 1073741823L));
  1438.          carry = x % (long)divisor;
  1439.       }
  1440.  
  1441.       return (int)carry;
  1442.    }
  1443.  
  1444.    private static void div(Bignum dvdnd, Bignum div, Bignum quot) {
  1445.       int divlen = div.value.length - 1;
  1446.       int d1 = div.value[divlen];
  1447.       int d2 = div.value[divlen - 1];
  1448.       int[] dndVal = dvdnd.value;
  1449.       int[] divVal = div.value;
  1450.       int qx = quot.value.length - 1;
  1451.  
  1452.       for(int j = dvdnd.value.length - 1; j > divlen; --j) {
  1453.          int dd0 = dndVal[j];
  1454.          int dd1 = dndVal[j - 1];
  1455.          int dd2 = dndVal[j - 2];
  1456.          long temp1 = ((long)dd0 << 30) + (long)dd1;
  1457.          long q;
  1458.          if (dd0 == d1) {
  1459.             q = 1073741823L;
  1460.          } else {
  1461.             q = temp1 / (long)d1;
  1462.          }
  1463.  
  1464.          while(true) {
  1465.             long p1 = (long)d2 * q;
  1466.             long p2 = temp1 - (long)d1 * q;
  1467.             p2 = (p2 << 30) + (long)dd2;
  1468.             if (p1 <= p2) {
  1469.                if (q == 0L) {
  1470.                   quot.value[qx--] = 0;
  1471.                } else {
  1472.                   int k = j - divlen - 1;
  1473.                   long carry = 0L;
  1474.  
  1475.                   for(int dk = 0; dk <= divlen; ++dk) {
  1476.                      long x1 = (long)divVal[dk] * q + carry;
  1477.                      int x2 = dndVal[k] - (int)(x1 & 1073741823L);
  1478.                      if (x2 < 0) {
  1479.                         dndVal[k++] = x2 + 1073741824;
  1480.                         carry = (x1 >> 30) + 1L;
  1481.                      } else {
  1482.                         dndVal[k++] = x2;
  1483.                         carry = x1 >> 30;
  1484.                      }
  1485.                   }
  1486.  
  1487.                   if (carry != 0L) {
  1488.                      int temp = dndVal[k] - (int)carry;
  1489.                      if (temp >= 0) {
  1490.                         dndVal[k] = temp;
  1491.                      } else {
  1492.                         dndVal[k] = temp + 1073741824;
  1493.                         carry = 0L;
  1494.                         k = j - divlen - 1;
  1495.                         --q;
  1496.  
  1497.                         for(int dk = 0; dk <= divlen; ++dk) {
  1498.                            long nv = (long)(divVal[dk] + dndVal[k]) + carry;
  1499.                            dndVal[k++] = (int)(nv & 1073741823L);
  1500.                            carry = nv >> 30;
  1501.                         }
  1502.  
  1503.                         if (carry == 1L) {
  1504.                            dndVal[k] = (int)((long)(dndVal[k] + 1) & 1073741823L);
  1505.                         }
  1506.                      }
  1507.                   }
  1508.  
  1509.                   quot.value[qx--] = (int)q;
  1510.                }
  1511.                break;
  1512.             }
  1513.  
  1514.             --q;
  1515.          }
  1516.       }
  1517.  
  1518.    }
  1519.  
  1520.    private static int pow(int b, int e) {
  1521.       if (e == 0) {
  1522.          return 1;
  1523.       } else if (e == 1) {
  1524.          return b;
  1525.       } else {
  1526.          int ans = b;
  1527.  
  1528.          int temp;
  1529.          for(temp = 1; e != 1; e >>= 1) {
  1530.             if ((e & 1) == 1) {
  1531.                temp *= ans;
  1532.             }
  1533.  
  1534.             ans *= ans;
  1535.          }
  1536.  
  1537.          return ans * temp;
  1538.       }
  1539.    }
  1540.  
  1541.    private static int[] mulAndAdd(int[] val, int m, int a) {
  1542.       int n = val.length - 1;
  1543.       long k = (long)a & 1073741823L;
  1544.       long x = (long)m & 1073741823L;
  1545.       int[] w = val;
  1546.       if (x != 0L) {
  1547.          for(int i = 0; i <= n; ++i) {
  1548.             long uv = ((long)val[i] & 1073741823L) * x + k;
  1549.             w[i] = (int)(uv & 1073741823L);
  1550.             k = uv >> 30;
  1551.          }
  1552.  
  1553.          if (k != 0L) {
  1554.             int[] ww = new int[w.length + 1];
  1555.             System.arraycopy(w, 0, ww, 0, w.length);
  1556.             ww[ww.length - 1] = (int)(k & 1073741823L);
  1557.             w = ww;
  1558.          }
  1559.       }
  1560.  
  1561.       return w == val ? null : w;
  1562.    }
  1563.  
  1564.    private Bignum(int[] valueArray) {
  1565.       this.value = valueArray;
  1566.       this.negative = false;
  1567.    }
  1568.  
  1569.    private static int[] mul0(int[] u, int[] v, int[] x) {
  1570.       int[] w = x;
  1571.  
  1572.       int n;
  1573.       for(n = u.length - 1; u[n] == 0; --n) {
  1574.       }
  1575.  
  1576.       int m;
  1577.       for(m = v.length - 1; v[m] == 0; --m) {
  1578.       }
  1579.  
  1580.       if (m >= 0 && n >= 0) {
  1581.          long k = 0L;
  1582.          int q = 0;
  1583.          int maxpos = 0;
  1584.          if (x == null || x.length < n + m + 3) {
  1585.             w = new int[n + m + 3];
  1586.          }
  1587.  
  1588.          for(int j = 0; j <= n; ++j) {
  1589.             k = 0L;
  1590.             q = j;
  1591.  
  1592.             for(int i = 0; i <= m; ++i) {
  1593.                long uv = (long)u[j];
  1594.                long t = uv * (long)v[i] + (long)w[q] + k;
  1595.                w[q++] = (int)(t & 1073741823L);
  1596.                k = t >> 30;
  1597.             }
  1598.  
  1599.             while(k != 0L) {
  1600.                long uv = (long)w[q] + k;
  1601.                w[q++] = (int)(uv & 1073741823L);
  1602.                k = uv >> 30;
  1603.             }
  1604.  
  1605.             if (q > maxpos) {
  1606.                maxpos = q;
  1607.             }
  1608.          }
  1609.  
  1610.          return w;
  1611.       } else {
  1612.          if (x == null) {
  1613.             w = new int[1];
  1614.          }
  1615.  
  1616.          w[0] = 0;
  1617.          return w;
  1618.       }
  1619.    }
  1620.  
  1621.    static {
  1622.       smallPrimes[0] = 2;
  1623.       smallPrimes[1] = 3;
  1624.       smallPrimes[2] = 5;
  1625.       smallPrimes[3] = 7;
  1626.       smallPrimes[4] = 11;
  1627.       smallPrimes[5] = 13;
  1628.       smallPrimes[6] = 17;
  1629.       smallPrimes[7] = 19;
  1630.       smallPrimes[8] = 23;
  1631.       smallPrimes[9] = 29;
  1632.       smallPrimes[10] = 31;
  1633.       smallPrimes[11] = 37;
  1634.       smallPrimes[12] = 41;
  1635.       smallPrimes[13] = 43;
  1636.       smallPrimes[14] = 47;
  1637.       smallPrimes[15] = 53;
  1638.       smallPrimes[16] = 59;
  1639.       smallPrimes[17] = 61;
  1640.       smallPrimes[18] = 67;
  1641.       smallPrimes[19] = 71;
  1642.       smallPrimes[20] = 73;
  1643.       smallPrimes[21] = 79;
  1644.       smallPrimes[22] = 83;
  1645.       smallPrimes[23] = 89;
  1646.       smallPrimes[24] = 97;
  1647.       smallPrimes[25] = 101;
  1648.       smallPrimes[26] = 103;
  1649.       smallPrimes[27] = 107;
  1650.       smallPrimes[28] = 109;
  1651.       smallPrimes[29] = 113;
  1652.       smallPrimes[30] = 127;
  1653.       smallPrimes[31] = 131;
  1654.       smallPrimes[32] = 137;
  1655.       smallPrimes[33] = 139;
  1656.       smallPrimes[34] = 149;
  1657.       smallPrimes[35] = 151;
  1658.       smallPrimes[36] = 157;
  1659.       smallPrimes[37] = 163;
  1660.       smallPrimes[38] = 167;
  1661.       smallPrimes[39] = 173;
  1662.       smallPrimes[40] = 179;
  1663.       smallPrimes[41] = 181;
  1664.       smallPrimes[42] = 191;
  1665.       smallPrimes[43] = 193;
  1666.       smallPrimes[44] = 197;
  1667.       smallPrimes[45] = 199;
  1668.       smallPrimes[46] = 211;
  1669.       smallPrimes[47] = 223;
  1670.       smallPrimes[48] = 227;
  1671.       smallPrimes[49] = 229;
  1672.       smallPrimes[50] = 233;
  1673.       roundingValue = 4;
  1674.       ZERO = new Bignum("0,0");
  1675.       ONE = new Bignum(1, 0);
  1676.       TWO = new Bignum(2, 0);
  1677.    }
  1678. }
  1679.